/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

#ifndef _MANDELBAUM_H_
#define _MANDELBAUM_H_

#include <list>
#include <vector>
#include <iostream>
#include "gmpxx.h"
#include "online-certifier/communicator/decoderCommunicator.hh"

using namespace std;
typedef mpz_class integer;
class Lifter {
	
	
	
private:

	integer _MaxModulus;
	vector <pair<integer,integer> > _RadixTable;
	
	
public:

	

	/*
	 * Constructor
	 */
	Lifter(): _MaxModulus (0) {
		pair<integer, integer> p (0, 0);
		_RadixTable.push_back (p);
	}
	
	/**
	 * \brief Update the Lifter status with one additional result
	 *
	 *  @param modulo: the modulo of the new result
	 *  @param residue: the residue of the new result
	 *  
	 */
	void AddOneValue (const long modulo, const long residue);

	/**
	 * \brief ...
	 *
	 * @param ...
	 */
	void GetCurrentResult (integer &residue, integer &modulus, integer &modulusMax);

	/**
	 * \brief...
	 */
	
	       
	
};


class Decoder {
	
	
	
private:

	integer _qi, _qi_1, _qi_2, _pi, _pi_1, _pi_2, _ri, _ri_1, _MaxModulus, _residue, _modulus, _bound;
	size_t _NbErrors;
	
	
public:

	
	/*
	 * Constructor
	 */
	

	Decoder(integer residue, integer modulus, integer MaxModulus, const size_t NbErrors): 
_pi (0), _pi_1 (1), _pi_2(0), _qi(0), _qi_2 (1), _MaxModulus (MaxModulus),_NbErrors(NbErrors),_residue(residue),_modulus(modulus) {
		mpz_fdiv_qr(_qi_1.get_mpz_t(),_ri.get_mpz_t(), _modulus.get_mpz_t(), _residue.get_mpz_t());
		_ri_1 = _residue;
		mpz_pow_ui(_bound.get_mpz_t(),_MaxModulus.get_mpz_t(),_NbErrors);;
		
	}
	
	/**
	 * \brief Update the Decoder status with one additional result
	 *
	 *  @param modulo: the modulo of the new result
	 *  @param residue: the residue of the new result
	 *  
	 */
	void One_Step_Euclide_Etendu();

	/**
	 * \brief ...
	 *
	 * @param ...
	 */
	void BoundDecode_And_SendResults(decoderCommunicator comm);

	

	
};




#endif
